<template>
  <el-card
    class="box-card"
    v-loading="tableLoading"
    element-loading-text="拼命加载中..."
  >
    <div class="operating-but">
      <hasRole
        v-for="item in tableConfig.globalOperate"
        :key="item.name"
        :permi="item.role"
      >
        <template v-if="item.enable == 1">
          <el-button
            @click="tableConfig.handlerOperate(item, selectionData)"
            :type="item.color"
            :disabled="selectionData.length !== 1"
            plain
            size="mini"
            :icon="item.icon"
          >
            {{ item.name }}
          </el-button>
        </template>
        <template v-else-if="item.enable == 2">
          <el-button
            @click="tableConfig.handlerOperate(item, selectionData)"
            :type="item.color"
            :disabled="selectionData.length === 0"
            plain
            size="mini"
            :icon="item.icon"
          >
            {{ item.name }}
          </el-button>
        </template>
        <el-button
          v-else
          @click="tableConfig.handlerOperate(item, selectionData)"
          :type="item.color"
          plain
          size="mini"
          :icon="item.icon"
        >
          {{ item.name }}
        </el-button>
      </hasRole>
    </div>
    <el-table
      :data="resPageData.list"
      :height="tableConfig.tableHeight"
      :stripe="tableConfig.stripe"
      :border="tableConfig.border"
      :size="tableConfig.size"
      :show-header="tableConfig.showHeader"
      :span-method="spanMethod"
      @select-all="selectAll"
      @sort-change="sortChange"
      row-key="id"
      :default-expand-all="tableConfig.expandAll"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
    >
      <el-table-column
        v-for="item in tableConfig.columns"
        :type="item.type"
        :key="item.field"
        :prop="item.field"
        :label="item.title"
        :width="item.width"
        :fixed="item.fixed"
        :show-overflow-tooltip="item.overflowTooltip"
        :align="item.align || 'center'"
        :class-name="item.className"
        :label-class-name="item.labelClassName"
        :sortable="item.sortable"
      >
        <template v-slot:header>
          <slot :name="`${item.field}Header`">
            <span @click="handlerHeader(item)">{{ item.title }}</span>
          </slot>
        </template>
        <template v-slot="scope">
          <span v-if="item.type == 'index'">
            {{
              tableConfig.pageNumber == 1
                ? scope.$index + 1
                : (tableConfig.pageNumber - 1) * tableConfig.pageSize +
                  scope.$index +
                  1
            }}
          </span>
          <el-checkbox
            @change="checkboxChange"
            v-if="item.type == 'selection'"
            v-model="scope.row['selection']"
          ></el-checkbox>
          <el-radio
            @change="radioChange(scope.$index)"
            v-if="item.type == 'radio'"
            :label="true"
            v-model="scope.row['selection']"
          >
            {{ "" }}
          </el-radio>
          <slot :name="item.field" :row="scope.row">
            <span @click="handlerTable(scope.row)">
              {{
                item.formatter
                  ? item.formatter(scope.row[item.field], scope.row)
                  : scope.row[item.field]
              }}
            </span>
          </slot>
        </template>
      </el-table-column>
      <el-table-column
        :width="tableConfig.operateWidth"
        v-if="tableConfig.operate.length !== 0"
        fixed="right"
        :align="tableConfig.operateAlign"
        label="操作"
      >
        <template v-slot="scope">
          <hasRole
            v-for="(item, i) in tableConfig.operate"
            :key="i"
            :permi="item.role"
          >
            <el-button
              @click="tableConfig.handlerOperate(item, [scope.row])"
              :type="item.type"
              size="mini"
              :icon="item.icon"
            >
              {{ item.name }}
            </el-button>
          </hasRole>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-if="tableConfig.hasPage"
      id="pagination"
      background
      :page-size="tableConfig.pageSize"
      :total="resPageData.total"
      v-model:current-page="tableConfig.pageNumber"
      layout="sizes, prev, pager, next, jumper, ->, total, slot"
      :page-sizes="tableConfig.pageSizes"
      @size-change="handlerSizeChange"
      @current-change="handlerCurrentChange"
    >
    </el-pagination>
  </el-card>
</template>

<script>
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import { debounce } from '@/utils/tools';
export default {
	props : {
		config : {
			type : Object,
			required : true
		}
	},
	setup (ctx) {
		let tableConfig = reactive({
			initApi : true, // 是否自动调用
			reqApiMethod : () => {}, // api 需要返回Promise
			handlerHeader : () => {}, // 表头点击
			handlerTable : () => {}, // 表格点击
			handlerSelectionChange : () => {}, // 单选/多选 触发
			mergeTable : () => {}, // 表格合并
			responseHandler : (list) => list, // 格式接口返回的数据
			queryParams : (params) => params, // 格式接口入参的数据
			handlerOperate : () => {}, // 按钮操作项事件
			expandAll : false, // 是否展开所有
			tableHeight : null, // table高
			showHeader : true, // 是否显示表头
			size : 'medium', // Table 的尺寸 medium / small / mini
			stripe : true, // 隔行变色
			border : false, // 是否带有纵向边框
			hasPage : true, // 是否分页
			pageNumber : 1, // 当前的页数
			pageSize : 10, // 每页展示条数
			pageSizes : [10, 20, 30], // 选择每一个展示的条数
			/**
       * 全局按钮操作项:顶部位置
       *  butType 唯一key
       *  type: '', // 类型
       *  enable: '' 操作按钮禁用状态 1 选中一个启用 2 选中一个或者多个启用
       *  name: "", // 文字
       *  color: "", // 颜色
       *  role: [], // 权限
       *  icon: "", // 图标
       */
			globalOperate : [],
			operateWidth : 120, // 列表操作项宽
			operateAlign : 'center', // 列表操作项对齐方式 left|center|right
			/**
       * 列表按钮操作项
       *  butType 唯一key
       *  type: '', // 类型
       *  name: "", // 文字
       *  color: "", // 颜色
       *  role: [], // 权限
       *  icon: "", // 图标
       */
			operate : [], // 列表操作项
			/**
       * 表头信息
       * type:expand 展开 |index 序号|selection 多选|radio 单选
       * title: 表头标题
       * field: 渲染列表的key
       * width: 表格宽
       * formatter: 格式化函数
       * overflowTooltip：超出文字展示...,
       * align: 对齐方式
       * className: 列的 className
       * labelClassName: 当前列标题的自定义类名
       * sortable:'custom' // 排序
       * field+Header: 表头插槽
       * field: 表格插槽
       */
			columns : [],
			...ctx.config
		});
		let tableLoading = ref(false);
		// 列表数据
		let resPageData = ref({
			list : [],
			total : 0
		});
		// 选择的数据
		let selectionData = ref([]);

		// 获取列表数据
		let fetchData = async ({ isResetPageNumber = false } = {}) => {
			tableLoading.value = true;
			selectionData.value = [];
			return new Promise((resolve) => {
				// 搜索重置页数
				if (isResetPageNumber) {
					tableConfig.pageNumber = 1;
				}
				// 过滤空数据
				let searchParams = {};
				Object.keys(ctx.config.searchParams).forEach((key) => {
					if (
						ctx.config.searchParams[key] !== '' &&
            ctx.config.searchParams[key] !== 'null' &&
            ctx.config.searchParams[key] !== 'undefined' &&
            ctx.config.searchParams[key] !== null &&
            ctx.config.searchParams[key] !== undefined
					) {
						searchParams[key] = ctx.config.searchParams[key];
					}
				});
				let queryForm = tableConfig.queryParams({
					pageNumber : tableConfig.pageNumber,
					pageSize : tableConfig.pageSize,
					...searchParams
				});
				// 是否分页
				if (!tableConfig.hasPage) {
					delete queryForm.pageNumber;
					delete queryForm.pageSize;
				}
				tableConfig
					.reqApiMethod(queryForm)
					.then((res) => {
						tableLoading.value = false;
						resPageData.value = tableConfig.responseHandler(res);
						resPageData.value.list &&
              resPageData.value.list.forEach((item) => {
              	item.selection = false;
              });
						resolve();
					})
					.catch(() => {
						tableLoading.value = false;
						resolve();
					});
			});
		};

		// 全选/反选
		let selectAll = (payload) => {
			resPageData.value.list.forEach(
				(item) => (item.selection = payload.length !== 0)
			);
			handlerSelectionChange(resPageData.value.list);
		};
		// 单选
		let radioChange = (index) => {
			resPageData.value.list.forEach(
				(item, i) => (item.selection = i === index)
			);
			handlerSelectionChange(resPageData.value.list);
		};
		// 复选
		let checkboxChange = () => {
			handlerSelectionChange(resPageData.value.list);
		};
		// 排序
		let sortChange = (column) => {
			console.log(column);
		};

		// 每页条数改变
		let handlerSizeChange = (val) => {
			tableConfig.pageSize = val;
			fetchData();
		};
		// 页数改变
		let handlerCurrentChange = (val) => {
			tableConfig.pageNumber = val;
			fetchData();
		};

		// 表头点击操作
		let handlerHeader = (payload) => {
			tableConfig.handlerHeader(payload);
		};
		// table单元格点击
		let handlerTable = (payload) => {
			tableConfig.handlerTable(payload);
		};

		// 表格跨行
		let spanMethod = ({ row, column, rowIndex, columnIndex }) => {
			return tableConfig.mergeTable({ row, column, rowIndex, columnIndex });
		};

		// 单选/多选 触发
		let handlerSelectionChange = () => {
			let res = resPageData.value.list.filter((item) => item.selection);
			selectionData.value = res;
			tableConfig.handlerSelectionChange(res);
		};

		if (tableConfig.initApi) {
			fetchData();
		}

		let screenDom = 0;
		let headerDom = 0;
		let searchDom = 0;
		let paginationDom = 0;
		// 动态计算列表高度
		let onResize = () => {
			let headerHeight = headerDom.clientHeight;
			let searchHeight = searchDom.clientHeight;
			let paginationHeight = paginationDom.clientHeight;
			tableConfig.tableHeight =
        screenDom - (headerHeight + searchHeight + paginationHeight + 120);
		};

		onMounted(() => {
			screenDom = document.body.clientHeight;
			headerDom = document.querySelector('#header') || { clientHeight : 0 };
			searchDom = document.querySelector('#search') || { clientHeight : 0 };
			paginationDom = document.querySelector('#pagination') || {
				clientHeight : 0
			};
			onResize();
			window.addEventListener('resize', debounce(onResize, 100));
		});

		// 解绑
		onUnmounted(() => {
			window.removeEventListener('resize', onResize);
		});

		return {
			tableConfig,
			tableLoading,
			resPageData,
			selectAll,
			checkboxChange,
			radioChange,
			sortChange,
			handlerSizeChange,
			handlerCurrentChange,
			handlerHeader,
			handlerTable,
			spanMethod,
			selectionData,
			fetchData
		};
	}
};
</script>

<style lang="scss" scoped>
.el-pagination {
  padding-top: 10px;
}
.operating-but {
  display: flex;
}
</style>
